package ReflectionLearn.RefleDeepLearn;

import ReflectionLearn.RefleDeepLearnClass.Person;
import org.junit.jupiter.api.Test;


import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author Lenl
 * @version v1.0
 * @create 2021-06-07 20:38
 * @description 调用运行时类的指定结构：属性、方法、构造器
 *
 */
public class ReflectionUseTest {
    /**
     * 调用属性
     * @throws Exception
     */
    @Test
    public void testField() throws Exception {
        Class clazz= Person.class;

        //创建运行时类的对象
        Person p= (Person) clazz.getDeclaredConstructor().newInstance();

        //获取指定的属性:要求属性声明为public，通常不使用该方式
        Field id = clazz.getField("id");
        //通常采用此方式，可获取private和缺省的属性
        Field name =clazz.getDeclaredField("name");
        //但是需要设置才有权限，保证当前属性是可访问的
        name.setAccessible(true);
        name.set(p,"tom");
        System.out.println(name.get(p));
        /*
        设置当前属性的值：
        set() 参数1：指明那个对象的属性，参数2：此属性的值设置为多少
         */
        id.set(p,1001);

        /**
         获取当亲的属性值
         get():参数：获取那个对象的属性
         */
        System.out.println(id.get(p));

    }

    /**
     * 调用方法
     */
    @Test
    public void testMethods() throws Exception{
        Class clazz= Person.class;
        //创建运行时类的对象
        Person p= (Person) clazz.getDeclaredConstructor().newInstance();
        //1.获取某个指定的方法
        //getDeclaredMethod():参数1：获取方法的名称 参数二：指明获取的方法的形参列表
        Method show= clazz.getDeclaredMethod("show",String.class);
        //2.保证当前方法是可用的
        show.setAccessible(true);
        /*
        invoke():参数1：方法的调用者 参数2：给方法赋值的实参
        返回值为对应类中调用方法的返回值
         */
        //3.调用方法
        Object returnVal= show.invoke(p,"CHN");
        System.out.println(returnVal);

        //private static void showDesc
        /*
        4.调用静态方法

         */
        Method staticMethod=clazz.getDeclaredMethod("showDesc");
        staticMethod.setAccessible(true);
        Object re= staticMethod.invoke(clazz); //此处的参数无意义，null也可
        //无返回值则返回null
        System.out.println(re);
    }

    /**
     * 调用构造器
     */
    @Test
    public void testConstructor() throws Exception{
        Class clazz=Person.class;
        //getDeclaredConstructor：参数：指明构造器的参数列表
        Constructor con=clazz.getDeclaredConstructor(String.class);

        //保证构造器可访问
        con.setAccessible(true);
        //创造对象
        Person p= (Person) con.newInstance("Tom");

        System.out.println(p);
    }

}
